﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;
using CommonLibrary.Data;

namespace CommonLibrary
{
    public static class ClT
    {
        /// <summary>
        /// In扩展
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool ClIn<T>(this T t, params T[] c)
        {
            if (t == null) throw new ArgumentNullException("参数错误");

            return c.Any(i => i.Equals(t));
        }

        /// <summary>
        /// NotIn扩展
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool ClNotIn<T>(this T t, params T[] c)
        {
            if (t == null) throw new ArgumentNullException("参数错误");

            return !c.Any(i => i.Equals(t));
        }

        /// <summary>
        /// 取最小值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="arr"></param>
        /// <returns></returns>
        public static T ClGetMin<T>(this T t, params T[] arr) where T : IComparable<T>
        {
            if (t == null) throw new ArgumentNullException("参数错误");

            List<T> list = new List<T>();
            list.Add(t);
            foreach (T item in arr)
            {
                list.Add(item);
            }
            list.Sort();

            return list[0];
        }

        /// <summary>
        /// 取最大值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="arr"></param>
        /// <returns></returns>
        public static T ClGetMax<T>(this T t, params T[] arr) where T : IComparable<T>
        {
            if (t == null) throw new ArgumentNullException("参数错误");

            List<T> list = new List<T>();
            list.Add(t);
            foreach (T item in arr)
            {
                list.Add(item);
            }
            list.Sort();

            return list[list.Count - 1];
        }

        /// <summary>
        /// 是否在...中
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="lowerBound"></param>
        /// <param name="upperBound"></param>
        /// <param name="includeLowerBound"></param>
        /// <param name="includeUpperBound"></param>
        /// <returns></returns>
        public static bool ClIsBetween<T>(this T t, T lowerBound, T upperBound, bool includeLowerBound = false, bool includeUpperBound = false) where T : IComparable<T>
        {
            if (t == null) throw new ArgumentNullException("参数错误");

            var lowerCompareResult = t.CompareTo(lowerBound);
            var upperCompareResult = t.CompareTo(upperBound);

            return (includeLowerBound && lowerCompareResult == 0) || (includeUpperBound && upperCompareResult == 0) || (lowerCompareResult > 0 && upperCompareResult < 0);
        }


        /// <summary>
        /// 先执行命令，再返回自身
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public static T ClDo<T>(this T t, Action<T> action)
        {
            action(t);
            return t;
        }

        /// <summary>
        /// 先执行命令，再返回自身
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="exp"></param>
        /// <returns></returns>
        public static IEnumerable<T> ClDo<T>(this IEnumerable<T> list, Action<T> exp)
        {
            //List<MG_ZONE_Model> list_MG_ZONE_Model = (new MG_ZONE_Model()).SelectData().ClDo(b => b.ZONE_NAME = "").ToList();
            foreach (var model in list)
            {
                exp(model);
            }
            return list;
        }

        /// <summary>
        /// 先执行命令，再返回自身
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="exp1"></param>
        /// <param name="exp2"></param>
        /// <returns></returns>
        public static IEnumerable<T> ClDo<T>(this IEnumerable<T> list, Func<T, bool> exp1, Action<T> exp2)
        {
            //List<MG_ZONE_Model> list_MG_ZONE_Model = (new MG_ZONE_Model()).SelectData().ClDo(a => a.LEVEL_ == 2, b => b.ZONE_NAME = "").ToList();
            foreach (var model in list)
            {
                if (exp1(model))
                {
                    exp2(model);
                }

            }
            return list;
        }


        /// <summary>
        /// 将集合转换为Objec[]的泛型方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tList"></param>
        /// <returns></returns>
        public static object[] ClToArray<T>(this IList<T> tList)
        {
            object[] array = new object[tList.Count];
            int i = 0;
            foreach (T t in tList)
            {
                array[i] = t;
                i++;
            }
            return array;
        }

        /// <summary>
        /// 深拷贝，类必须声明[Serializable]
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="a"></param>
        /// <returns></returns>

        public static T ClCopyDeep<T>(this T a)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, a);
                stream.Position = 0;
                return (T)formatter.Deserialize(stream);
            }
        }

        #region 序列化与反序列化对象

        /// <summary>
        /// To convert a Byte Array of Unicode values (UTF-8 encoded) to a complete String.
        /// </summary>
        /// <param name="characters">Unicode Byte Array to be converted to String</param>
        /// <returns>String converted from Unicode Byte Array</returns>
        private static string UTF8ByteArrayToString(byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            string constructedString = encoding.GetString(characters);
            return (constructedString);
        }

        /// <summary>
        /// Converts the String to UTF8 Byte array and is used in De serialization
        /// </summary>
        /// <param name="pXmlString"></param>
        /// <returns></returns>
        private static Byte[] StringToUTF8ByteArray(string pXmlString)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            byte[] byteArray = encoding.GetBytes(pXmlString);
            return byteArray;
        }

        /// <summary>
        /// Serialize an object into an XML string
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string SerializeObjectToXml<T>(this T obj)
        {
            try
            {
                string xmlString = null;
                MemoryStream memoryStream = new MemoryStream();
                XmlSerializer xs = new XmlSerializer(typeof(T));
                Encoding utf8EncodingWithNoByteOrderMark = new UTF8Encoding(false);//使用utf8EncodingWithNoByteOrderMark，避免前头有字符65279
                XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, utf8EncodingWithNoByteOrderMark);
                xs.Serialize(xmlTextWriter, obj);
                memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                xmlString = UTF8ByteArrayToString(memoryStream.ToArray());
                memoryStream.Close();

                return xmlString;
            }
            catch
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// Reconstruct an object from an XML string
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        public static T DeserializeObjectFromXml<T>(string xml)
        {
            XmlSerializer xs = new XmlSerializer(typeof(T));
            MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(xml));
            XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
            return (T)xs.Deserialize(memoryStream);
        }

        /// <summary>
        /// 序列化到Xml文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        public static bool SerializeObjectToXmlFile<T>(this T obj, string file)
        {
            if (File.Exists(file))
            {
                return false;
            }

            StreamWriter writer = new StreamWriter(file, false, System.Text.Encoding.UTF8);
            writer.Write(obj.SerializeObjectToXml());
            writer.Close();

            return true;
        }

        /// <summary>
        /// 从Xml文件反序列化对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="file"></param>
        /// <returns></returns>
        public static T DeserializeObjectFromXmlFile<T>(string file)
        {
            if (File.Exists(file) == false)
            {
                return default(T);
            }
            StreamReader reader = new StreamReader(file, System.Text.Encoding.UTF8);
            string xml = reader.ReadToEnd();
            reader.Close();

            return (T)DeserializeObjectFromXml<T>(xml);
        }


        /// <summary>
        /// 序列化到文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        public static bool SerializeObjectToBinaryFile<T>(this T obj, string file)
        {
            if (File.Exists(file))
            {
                return false;
            }

            using (Stream stream = File.Create(file))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, obj);
            }
            return true;
        }

        /// <summary>
        /// 从文件反序列化对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="file"></param>
        /// <returns></returns>
        public static T DeserializeObjectFromBinaryFile<T>(string file)
        {
            if (File.Exists(file) == false)
            {
                return default(T);
            }

            using (Stream stream = File.Open(file, FileMode.Open))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                return (T)formatter.Deserialize(stream);
            }

        }

        #endregion


        /// <summary>
        /// Dictionary输入XML文件
        /// </summary>
        /// <param name="dictionary"></param>
        /// <param name="xmlFile"></param>
        /// <returns></returns>
        public static bool ClWriteXml(this Dictionary<string, string> dictionary, string xmlFile)
        {
            if (File.Exists(xmlFile))
            {
                return false;
            }

            // serialize the dictionary
            DataContractSerializer serializer = new DataContractSerializer(dictionary.GetType());
            using (StringWriter sw = new StringWriter())
            {
                using (XmlTextWriter writer = new XmlTextWriter(sw))
                {
                    // add formatting so the XML is easy to read in the log
                    writer.Formatting = System.Xml.Formatting.Indented;
                    serializer.WriteObject(writer, dictionary);
                    writer.Flush();
                    string xml = sw.ToString();

                    using (StreamWriter wr = new StreamWriter(xmlFile, false, System.Text.Encoding.UTF8))
                    {
                        wr.Write(xml);
                    }
                }
            }
            return true;
        }



        /// <summary>
        /// 尝试将项添加到List中
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static List<T> ClTryAdd<T>(this List<T> list, T t)
        {
            if (list.Contains(t) == false)
            {
                list.Add(t);
            }
            return list;
        }

        /// <summary>
        /// 尝试将键和值添加到字典中：如果不存在，才添加；存在，不添加也不抛导常
        /// </summary>
        public static Dictionary<TKey, TValue> ClTryAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue value)
        {
            if (dict.ContainsKey(key) == false) dict.Add(key, value);
            return dict;
        }
        /// <summary>
        /// 将键和值添加或替换到字典中：如果不存在，则添加；存在，则替换
        /// </summary>
        public static Dictionary<TKey, TValue> ClAddOrReplace<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue value)
        {
            dict[key] = value;
            return dict;
        }

        /// <summary>
        /// 获取与指定的键相关联的值，如果没有则返回输入的默认值
        /// </summary>
        public static TValue ClGetValue<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue defaultValue = default(TValue))
        {
            return dict.ContainsKey(key) ? dict[key] : defaultValue;
        }

        /// <summary>
        /// 向字典中批量添加键值对
        /// </summary>
        /// <param name="replaceExisted">如果已存在，是否替换</param>
        public static Dictionary<TKey, TValue> ClAddRange<TKey, TValue>(this Dictionary<TKey, TValue> dict, IEnumerable<KeyValuePair<TKey, TValue>> values, bool replaceExisted)
        {
            foreach (var item in values)
            {
                if (dict.ContainsKey(item.Key) == false || replaceExisted)
                    dict[item.Key] = item.Value;
            }
            return dict;
        }


        /// <summary>
        /// 删除字典中的一个记录
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dict"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool ClRemove<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, out TValue value)
        {
            dict.TryGetValue(key, out value);
            return dict.Remove(key);
        }


        public static IEnumerable<T> GetDescendants<T>(this T root, Func<T, IEnumerable<T>> childSelector, Predicate<T> filter)
        {
            foreach (T t in childSelector(root))
            {
                if (filter == null || filter(t))
                {
                    yield return t;
                }

                foreach (T child in GetDescendants((T)t, childSelector, filter))
                {
                    yield return child;
                }
            }

            #region 调用例子

            //Form1.cs
            //获取本窗体所有控件

            //var controls = (this as Control).GetDescendants(c => c.Controls.Cast<Control>(), null);
            ////获取所有选中的CheckBox
            //var checkBoxes = (this as Control).GetDescendants(
            //        c => c.Controls.Cast<Control>(),
            //        c => (c is CheckBox) && (c as CheckBox).Checked
            //    )
            //    .Cast<CheckBox>();

            #endregion
        }


        public static IEnumerable<T> GetDescendants<TRoot, T>(this TRoot root, Func<TRoot, IEnumerable<T>> rootChildSelector, Func<T, IEnumerable<T>> childSelector, Predicate<T> filter)
        {
            foreach (T t in rootChildSelector(root))
            {
                if (filter == null || filter(t))
                {
                    yield return t;
                }

                foreach (T child in GetDescendants(t, childSelector, filter))
                {
                    yield return child;
                }
            }

            #region 调用例子

            //获取TreeView中所有以“酒”结尾的树结点             

            //var treeViewNode = treeView1.GetDescendants(
            //    treeView => treeView.Nodes.Cast<TreeNode>(),
            //    treeNode => treeNode.Nodes.Cast<TreeNode>(),
            //    treeNode => treeNode.Text.EndsWith("酒")
            //    );

            #endregion
        }



        public static T ClIf<T>(this T t, Predicate<T> predicate, params Action<T>[] actions) where T : class
        {
            if (t == null) throw new ArgumentNullException();
            if (predicate(t))
            {
                foreach (var action in actions)
                    action(t);
            }
            return t;

            #region 调用例子

            ////常规代码
            //People people1 = new People { Name = "ldp615", IsHungry = true, IsThirsty = true, IsTired = true };
            //if (people1.IsHungry) people1.Eat();
            //if (people1.IsThirsty) people1.Drink();
            //if (people1.IsTired) people1.Rest();
            //people1.Work();
            ////使用扩展方法
            //People people2 = new People { Name = "ldp615", IsHungry = true, IsThirsty = true, IsTired = true }
            //    .If(p => p.IsHungry, p => p.Eat())
            //    .If(p => p.IsThirsty, p => p.Drink())
            //    .If(p => p.IsTired, p => p.Rest());
            //people2.Work();

            #endregion
        }


        public static T ClIf<T>(this T t, Predicate<T> predicate, Func<T, T> func) where T : struct
        {
            return predicate(t) ? func(t) : t;
        }

        public static string ClIf(this string s, Predicate<string> predicate, Func<string, string> func)
        {
            return predicate(s) ? func(s) : s;
        }

        public static void ClWhile<T>(this T t, Predicate<T> predicate, params Action<T>[] actions) where T : class
        {
            while (predicate(t))
            {
                foreach (var action in actions)
                    action(t);
            }
        }


        /// <summary>
        /// Lambda递归调用
        /// 例子:var fix = Fix<int, int>(f => n => n == 0 ? 1 : n * f(n - 1));//加条件判断是否递归
        /// var result = fix(5);   // 120 = 5*4*3*2*1
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="f"></param>
        /// <returns></returns>
        public static Func<T, TResult> Fix<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> f)
        {
            return t => f(Fix(f))(t);
        }


        /// <summary>
        /// Dictionary<string, string>转换为对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        public static T DictionaryToObject<T>(this Dictionary<string, string> dictionary)
        {
            string jsonTemp = "\"{0}\":\"{1}\",";
            StringBuilder jsonString = new StringBuilder();
            jsonString.Append("{");
            foreach (KeyValuePair<string, string> keyValuePair in dictionary)
            {
                jsonString.AppendFormat(jsonTemp, keyValuePair.Key, keyValuePair.Value);
            }
            jsonString.Append("}");
            jsonString.Remove(jsonString.Length - 2, 1);

            try
            {
                return JSS.DeserializeObjectFromJson<T>(jsonString.ToString());
            }
            catch
            {
                return default(T);
            }
        }

        /// <summary>
        /// Dictionary<string, string>转换为对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        public static T DictionaryToObject<T>(this Dictionary<string, bool> dictionary)
        {
            string jsonTemp = "\"{0}\":\"{1}\",";
            StringBuilder jsonString = new StringBuilder();
            jsonString.Append("{");
            foreach (KeyValuePair<string, bool> keyValuePair in dictionary)
            {
                jsonString.AppendFormat(jsonTemp, keyValuePair.Key, keyValuePair.Value);
            }
            jsonString.Append("}");
            jsonString.Remove(jsonString.Length - 2, 1);

            try
            {
                return JSS.DeserializeObjectFromJson<T>(jsonString.ToString());
            }
            catch
            {
                return default(T);
            }
        }

        /// <summary>
        /// DictionaryToDataTable
        /// </summary>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        public static DataTable DictionaryToDataTable(this IDictionary<string, string> dictionary)
        {
            DataTable result = new DataTable("DictionaryToDataTable");
            if (dictionary.Count == 0) return result;

            result.Columns.AddRange(dictionary.Select(a => new DataColumn(a.Key)).ToArray());

            result.Rows.Add(dictionary.Select(c => c.Value).Cast<object>().ToArray());

            return result;
        }

        /// <summary>
        /// DistinctBy
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="items"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> property)
        {
            //var uniqueCars = cars.DistinctBy(x => x.CarCode);

            return items.GroupBy(property).Select(x => x.First());
        }


        public static IList<TR> FullOuterGroupJoin<TA, TB, TK, TR>(this IEnumerable<TA> a, IEnumerable<TB> b, Func<TA, TK> selectKeyA, Func<TB, TK> selectKeyB, Func<IEnumerable<TA>, IEnumerable<TB>, TK, TR> projection, IEqualityComparer<TK> cmp = null)
        {
            cmp = cmp ?? EqualityComparer<TK>.Default;
            var alookup = a.ToLookup(selectKeyA, cmp);
            var blookup = b.ToLookup(selectKeyB, cmp);

            var keys = new HashSet<TK>(alookup.Select(p => p.Key), cmp);
            keys.UnionWith(blookup.Select(p => p.Key));

            var join = from key in keys
                       let xa = alookup[key]
                       let xb = blookup[key]
                       select projection(xa, xb, key);

            return join.ToList();
        }

        public static IList<TR> FullOuterJoin<TA, TB, TK, TR>(this IEnumerable<TA> a, IEnumerable<TB> b, Func<TA, TK> selectKeyA, Func<TB, TK> selectKeyB, Func<TA, TB, TK, TR> projection, TA defaultA = default(TA), TB defaultB = default(TB), IEqualityComparer<TK> cmp = null)
        {
            cmp = cmp ?? EqualityComparer<TK>.Default;
            var alookup = a.ToLookup(selectKeyA, cmp);
            var blookup = b.ToLookup(selectKeyB, cmp);

            var keys = new HashSet<TK>(alookup.Select(p => p.Key), cmp);
            keys.UnionWith(blookup.Select(p => p.Key));

            var join = from key in keys
                       from xa in alookup[key].DefaultIfEmpty(defaultA)
                       from xb in blookup[key].DefaultIfEmpty(defaultB)
                       select projection(xa, xb, key);

            return join.ToList();
        }

        /// <summary>
        /// 复制两个实体类
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="source"></param>
        /// <param name="result"></param>
        /// <param name="overwrite"></param>
        public static void CopyEntity<TSource, TResult>(TSource source, ref TResult result, bool overwrite)
        {
            PropertyInfo[] propertys = typeof(TSource).GetProperties(); //获取此实体的公共属性
            foreach (PropertyInfo pi in propertys)
            {
                PropertyInfo des = typeof(TResult).GetProperty(pi.Name);
                if (des != null && des.PropertyType == pi.PropertyType && des.CanWrite && pi.CanRead)
                {
                    object desValue = des.GetValue(result, null);
                    if ((overwrite == false) && (desValue != null)) continue;

                    des.SetValue(result, pi.GetValue(source, null), null);
                }

            }
        }

        /// <summary>
        /// 复制两个实体类
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="source"></param>
        /// <param name="result"></param>
        public static void CopyEntity<TSource, TResult>(TSource source, ref TResult result)
        {
            CopyEntity(source, ref result, true);
        }

    }









    internal sealed class ReflectionDynamicObject : DynamicObject
    {
        private object RealObject { get; set; }

        public override bool TryConvert(ConvertBinder binder, out object result)
        {
            result = this.RealObject;
            return true;
        }
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            PropertyInfo property = this.RealObject.GetType().GetProperty(binder.Name, BindingFlags.GetProperty |
                BindingFlags.Public | BindingFlags.Instance);
            if (property == null)
            {
                result = null;
            }
            else
            {
                result = property.GetValue(this.RealObject, null);
                result = WrapObjectIfInternal(result);
            }
            return true;
        }
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            result = this.RealObject.GetType().InvokeMember(binder.Name, BindingFlags.InvokeMethod | BindingFlags.NonPublic |
                BindingFlags.Public | BindingFlags.Instance, null, this.RealObject, args, CultureInfo.InvariantCulture);
            return true;
        }
        public static object WrapObjectIfInternal(object o)
        {
            if (o == null) return null;
            if (o.GetType().IsPublic) return o;
            return new ReflectionDynamicObject { RealObject = o };
        }
        public override string ToString()
        {
            return this.RealObject.ToString();
        }
    }




}


namespace System.Linq
{
    public static class WhereIfExtension
    {
        public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate, bool condition)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, Expression<Func<T, int, bool>> predicate, bool condition)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool condition)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, Func<T, int, bool> predicate, bool condition)
        {
            return condition ? source.Where(predicate) : source;
        }
    }
}
